package com.derbysoft.lowcostadapter.commons.redis.utils;

import org.joda.time.DateTime;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public abstract class DateUtils {
    public static final int ONE_THOUSAND = 1000;
    private static final long MILLISECONDS_IN_DAY = 24 * 60 * 60 * ONE_THOUSAND;
    public static final int AMOUNT = -30;

    private static ThreadLocal threadLocal = new ThreadLocal() {
        protected synchronized Object initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };

    public static List<Date> getDateRangeDays(String start, String end) {
        return getDateRangeDays(of(start), of(end));
    }

    public static List<Date> getDateRangeDays(Date start, Date end) {
        List<Date> result = new ArrayList<Date>();
        for (Date day = start; day.compareTo(end) <= 0; day = nextDay(day)) {
            result.add(day);
        }
        return result;
    }

    public static List<Date> getStayDateRangeDays(Date checkInDate, Date checkOutDate) {
        return getDateRangeDays(checkInDate, DateUtils.addDays(checkOutDate, -1));
    }

    public static Date nextDay(Date date) {
        return addDays(date, 1);
    }

    public static Date before30seconds(Date date) {
        if (date == null) {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.SECOND, AMOUNT);
        return calendar.getTime();
    }

    public static Date addDays(Date date, int i) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, i);
        return calendar.getTime();
    }

    public static Date of(String date) {
        try {
            return getDayFormatter().parse(date);
        } catch (ParseException e) {
            throw new RuntimeException("parse date [" + date + "] failed in use [" + getDayFormatter() + "]", e);
        }
    }

    public static Date of(Date date) {
        return of(format(date));
    }

    public static String format(Date date) {
        return getDayFormatter().format(date);
    }

    public static String formatHHmmss(Date date) {
        return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(date);
    }

    public static int getDistanceBetween2Date(Date startDate, Date endDate) {
        return (int) ((endDate.getTime() - startDate.getTime()) / MILLISECONDS_IN_DAY);
    }

    public static long getUnixTime(Date date) {
        return date.getTime() / ONE_THOUSAND;
    }

    public static Date addHours(Date date, int hours) {
        return new DateTime(date.getTime()).plusHours(hours).toDate();
    }

    public static SimpleDateFormat getDayFormatter() {
        return (SimpleDateFormat) threadLocal.get();
    }

    public static Calendar getUTCCalendar() {
        Calendar calendar = Calendar.getInstance();
        int zoneOffset = calendar.get(Calendar.ZONE_OFFSET);
        int dstOffset = calendar.get(Calendar.DST_OFFSET);
        calendar.add(Calendar.MILLISECOND, -(zoneOffset + dstOffset));
        return calendar;
    }

    public static Calendar getUTCCalendar(Date date) {
        Calendar calendar = getUTCCalendar();
        calendar.setTime(date);
        return calendar;
    }

    public static boolean isIn(Date checkInDate, Date checkOutDate, Date date) {
        return checkInDate.compareTo(date) <= 0 && checkOutDate.compareTo(date) > 0;
    }

    public static boolean between(String startDate, String endDate, String date) {
        return date.compareTo(startDate) >= 0 && endDate.compareTo(date) >= 0;
    }
}
